package com.hongyi.system.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hongyi.common.framework.constant.CacheConstants;
import com.hongyi.common.framework.constant.Constants;
import com.hongyi.common.framework.constant.HttpStatus;
import com.hongyi.common.framework.domain.LoginBody;
import com.hongyi.common.framework.domain.LoginUser;
import com.hongyi.common.framework.domain.LoginVo;
import com.hongyi.common.framework.exception.ServiceException;
import com.hongyi.common.framework.strategy.IAuthStrategy;
import com.hongyi.common.framework.utils.common.ObjectUtils;
import com.hongyi.common.framework.utils.string.StringUtils;
import com.hongyi.common.redis.utils.RedisUtils;
import com.hongyi.common.saToken.utils.LoginUtils;
import com.hongyi.system.domain.SysUser;
import com.hongyi.system.domain.vo.SysUserVo;
import com.hongyi.system.mapper.SysUserMapper;
import com.hongyi.system.service.IAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 系统用户账号密码登录
 * 
 * @author DingHao
 */
@Service(value = "sysPassword")
public class SystemPasswordAuthStrategy implements IAuthStrategy {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private IAuthService authService;

    //验证码使用开关
    @Value("${captcha.enable}")
    private boolean captchaEnable;
    
    @Override
    public LoginVo authLogin(LoginBody loginBody) {
        String username = loginBody.getUsername();
        String password = loginBody.getPassword();
        String code = loginBody.getCode();
        String uuid = loginBody.getUuid();
        String deviceType = loginBody.getDeviceType();

        //如果验证码开关打开,校验验证码
        if (captchaEnable) {
            validateCaptcha(username, code, uuid);
        }
        //校验并获取用户信息
        SysUserVo sysUser = getSysUser(username);
        //校验密码
        authService.checkLogin(username,()->!BCrypt.checkpw(password, sysUser.getPassword()));
        //构建登录用户
        LoginUser loginUser = authService.buildLoginUser(sysUser,deviceType);
        //用户登录
        LoginUtils.login(loginUser,null);
        //返回登录信息
        LoginVo loginVo = new LoginVo();
        loginVo.setAccessToken(StpUtil.getTokenValue());
        loginVo.setLoginUser(loginUser);
        return loginVo;
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     */
    private void validateCaptcha(String username, String code, String uuid) {
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
        String captcha = RedisUtils.getCacheObject(verifyKey);
        RedisUtils.deleteObject(verifyKey);
        if (captcha == null) {
            authService.recordLoginInformation(username, Constants.LOGIN_FAIL,"验证码失效,请重新获取");
            throw new ServiceException("验证码失效,请重新获取",HttpStatus.ERROR);
        }
        if (!code.equalsIgnoreCase(captcha)) {
            authService.recordLoginInformation(username, Constants.LOGIN_FAIL,"验证码输入错误");
            throw new ServiceException("验证码输入错误",HttpStatus.BAD_REQUEST);
        }
    }

    /**
     * 校验并获取用户信息
     *
     * <p>描述：排除用户不存在、停用</p>
     */
    private SysUserVo getSysUser(String userName ) {
        SysUserVo sysUserVo = sysUserMapper.selectUserByUserName(userName);
        if (ObjectUtils.isNull(sysUserVo)) {
            throw new ServiceException("用户'"+userName+"'不存在");
        } else if (Constants.DISABLE.equals(sysUserVo.getStatus())) {
            throw new ServiceException("该用户已停用",HttpStatus.ERROR);
        }
        return sysUserVo;
    }
    
}
